package com.example.gulimall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.example.common.constant.ProductConstant;
import com.example.gulimall.product.dao.AttrAttrgroupRelationDao;
import com.example.gulimall.product.dao.AttrGroupDao;
import com.example.gulimall.product.dao.CategoryDao;
import com.example.gulimall.product.entity.AttrAttrgroupRelationEntity;
import com.example.gulimall.product.entity.AttrGroupEntity;
import com.example.gulimall.product.entity.CategoryEntity;
import com.example.gulimall.product.service.AttrAttrgroupRelationService;
import com.example.gulimall.product.service.CategoryService;
import com.example.gulimall.product.vo.AttrRespVo;
import com.example.gulimall.product.vo.AttrVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.utils.PageUtils;
import com.example.common.utils.Query;

import com.example.gulimall.product.dao.AttrDao;
import com.example.gulimall.product.entity.AttrEntity;
import com.example.gulimall.product.service.AttrService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;


@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {

    //里面有mybaties 封装的方法
    @Autowired
    AttrDao attrDao;
    @Autowired
    AttrGroupDao attrGroupDao;
    @Autowired
    CategoryDao categoryDao;
    @Autowired
    AttrAttrgroupRelationDao relationDao;

    @Autowired
    CategoryService categoryService;
    // 继承了这个类ServiceImpl里面封装了mybatis方法是人人开源封装的
    @Autowired
    AttrAttrgroupRelationService attrAttrgroupRelationService;
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<AttrEntity>()
        );

        return new PageUtils(page);
    }
    @Override
    public void saveAttr(AttrVo attrVo) {
        AttrEntity attrEntity=new AttrEntity();
        BeanUtils.copyProperties(attrVo,attrEntity);
        //1 报存基本数据
        this.save(attrEntity);
        //2 报存关联数据 销售属性没有分组，因此只有基础属性才保存关联关系
        if (attrVo.getAttrType()== ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity=new AttrAttrgroupRelationEntity();
            attrAttrgroupRelationEntity.setAttrId(attrEntity.getAttrId());
            attrAttrgroupRelationEntity.setAttrGroupId(attrVo.getAttrGroupId());
            attrAttrgroupRelationService.save(attrAttrgroupRelationEntity);
        }


    }

    @Override
    public PageUtils listAttr(Map<String, Object> params, Long catelogId, String type) {
      QueryWrapper<AttrEntity> queryWrapper=new QueryWrapper<AttrEntity>().
              eq("attr_type","base".equals(type)?ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode():
                      ProductConstant.AttrEnum.ATTR_TYPE_SASE.getCode());
        if (catelogId!=0){
            queryWrapper.eq("catelog_id",catelogId);
        }
        String key=params.get("key").toString();
        if (!StringUtils.isEmpty(key)){
            queryWrapper.and((wrapper)->{
                wrapper.eq("attr_id",catelogId).or().like("attr_name",key);
            });

        }
       IPage<AttrEntity> page=this.page(new Query<AttrEntity>().getPage(params),
               queryWrapper);
        //由于前端还要显示分组名和分类名他们是存在关系表中，我们不建议使用关联查询，因为产生的关联数据笛卡尔积特别大

        PageUtils pageUtils = new PageUtils(page);
        //分页记录
        List<AttrEntity> records = page.getRecords();
        //流式编程
        List<AttrRespVo> respVos = records.stream().map((attrEntity) -> {
            AttrRespVo attrRespVo = new AttrRespVo();
            //将attrEntity拷贝到attrRespVo返回 attrEntity箭头函数表示records
            BeanUtils.copyProperties(attrEntity, attrRespVo);

            //1、设置分类和分组的名字
            //if("base".equalsIgnoreCase(type)){
            //根据属性对象id查找关联表数据 销售属性没有分组，因此如果是销售属性的查询则不用设置
            if ("base".equalsIgnoreCase(type)){
                AttrAttrgroupRelationEntity attrId = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));
                if (attrId != null && attrId.getAttrGroupId()!=null) {
                    //查找分组名
                    AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrId.getAttrGroupId());
                    attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }


           // }
            //查找分类名
            CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
            if (categoryEntity != null) {
                attrRespVo.setCatelogName(categoryEntity.getName());
            }
            return attrRespVo;
        }).collect(Collectors.toList());

        pageUtils.setList(respVos);

        return pageUtils;

    }

   @Cacheable(value = "attr",key = "'attrinfo:'+#root.args[0]")
    @Override
    public AttrRespVo getByAttrId(Long attrId) {
        AttrRespVo attrRespVo=new AttrRespVo();
        //获取属性基本信息
        AttrEntity attrEntity=this.attrDao.selectById(attrId);
        BeanUtils.copyProperties(attrEntity,attrRespVo);

        if (attrEntity.getAttrType()==ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            //获取分组信息， 这里我们暂时只设置一个属性一个分组，暂时还没有用关联表设置一个属性多个分组
            AttrAttrgroupRelationEntity attrgroupRelationEntity= relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>()
                    .eq("attr_id",attrId));
            if (attrgroupRelationEntity!=null){
                AttrGroupEntity attrGroupEntity=attrGroupDao.selectById(attrgroupRelationEntity.getAttrGroupId());
                if (attrGroupEntity!=null){
                    attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }
        }

        //获取并设置分类信息
        //分类名
        CategoryEntity categoryEntity=categoryDao.selectById(attrEntity.getCatelogId());
        if (categoryEntity!=null){
            attrRespVo.setCatelogName(categoryEntity.getName());
        }
        //获取层级分类路径
        Long[] catelogPath=categoryService.getFindCategoryPath(attrEntity.getCatelogId());
        if (catelogPath!=null){
            attrRespVo.setCatelogPath(catelogPath);
        }
        return attrRespVo;
    }

    @Transactional
    @Override
    public void updateAttr(AttrVo attr) {
        AttrEntity attrEntity=new AttrEntity();
        //基本修改
        BeanUtils.copyProperties(attr,attrEntity);
        this.updateById(attrEntity);
        if (attrEntity.getAttrType()==ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            //修改分组关联
            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity=new AttrAttrgroupRelationEntity();
            //设置 分组id
            attrAttrgroupRelationEntity.setAttrGroupId(attr.getAttrGroupId());
            //设置属性id
            attrAttrgroupRelationEntity.setAttrId(attr.getAttrId());
            relationDao.update(attrAttrgroupRelationEntity,new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id",attr.getAttrId()));
        }


    }

    @Transactional
    @Override
    public void removeAttr(Long[] asList) {

       //查询出是基本属性还是销售属性，销售属性没有关联关系，不需要删除关联表

        //关联表删除

        for (Long item:asList) {
            AttrEntity attrEntity=attrDao.selectById(item.intValue());
            if (attrEntity.getAttrType()==1){
                relationDao.delete(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id",item));
            }

        }
        //属性基本删除
      this.removeByIds(Arrays.asList(asList));

    }

    /**
     * 根据分组id 查找该分组下所有属性
     * @param attgroupId
     * @return
     */
    @Override
    public List<AttrEntity> getRelationAttr(Long attgroupId) {
        List<AttrAttrgroupRelationEntity> relationEntities=relationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>()
        .eq("attr_group_id",attgroupId));
        List<AttrEntity> list=new ArrayList<>();
        for (AttrAttrgroupRelationEntity item:relationEntities) {
            AttrEntity attrEntity=attrDao.selectById(item.getAttrId());
           if (attrEntity!=null){
               list.add(attrEntity);
           }
        }

        return list;
    }

    /**
     * 获取当前分组没有关联的所有属性
     * @param attgroupId
     * @param params
     * @return
     */

    @Override
    public PageUtils getNoRelation(Long attrgroupId, Map<String, Object> params) {
        //1、当前分组只能关联自己所属的分类里面的所有属性，并且只能关联自己分类下的其他分组没有关联的属性
        AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupId);
        Long catelogId = attrGroupEntity.getCatelogId();
        //2、当前分组只能关联别的分组没有引用的属性
        //2.1)、当前分类下的其他分组
        List<AttrGroupEntity> group = attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId));
        List<Long> collect = group.stream().map(item -> {
            return item.getAttrGroupId();
        }).collect(Collectors.toList());

        //2.2)、这些分组关联的属性
        List<AttrAttrgroupRelationEntity> groupId = relationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id", collect));
        List<Long> attrIds = groupId.stream().map(item -> {
            return item.getAttrId();
        }).collect(Collectors.toList());

        //2.3)、从当前分类的所有属性中移除这些属性,并且只能是基本属性，不包括销售属性；
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>().eq("catelog_id", catelogId).eq("attr_type", ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());
        if(attrIds!=null && attrIds.size()>0){
            wrapper.notIn("attr_id", attrIds);
        }
        String key = (String) params.get("key");
        if(!StringUtils.isEmpty(key)){
            wrapper.and((w)->{
                w.eq("attr_id",key).or().like("attr_name",key);
            });
        }
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), wrapper);

        PageUtils pageUtils = new PageUtils(page);

        return pageUtils;
    }

    @Override
    public List<Long> selectSearchAttrs(List<Long> attrIds) {
       return baseMapper.selectSearchAttrs(attrIds);
    }


}